package com.spring.ioc.core;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;

/**
 * ClassPathXmlApplicationContext
 * @author ben
 * @date 20220413
 */
public class ClassPathXmlApplicationContext implements BeanFactory{
	private Map<String, Object> beans = new HashMap<String, Object>(); // ioc 容器
    
    public ClassPathXmlApplicationContext() throws Exception {
    	System.out.println("容器初始化...");
    	this.iocInit();
		System.out.println("初始化完毕...");
    }

    /**
     * 容器初始化
     * @throws Exception
     */
    private void iocInit() throws Exception {
    	SAXBuilder saxBuilder = new SAXBuilder();
		Document xmlDoc = saxBuilder
			.build(this.getClass().getClassLoader().getResourceAsStream("com/spring/config/beans.xml"));// 获取构造文档对象
		Element root = xmlDoc.getRootElement();// 获取根元素(beans)
		List<Element> beanlist = root.getChildren("bean");// 获取beans下所有的bean元素
		for (Element bean : beanlist) {
			String id = bean.getAttributeValue("id");//获取bean的id
			String clazz = bean.getAttributeValue("class");//bean的class
			Object object = Class.forName(clazz).newInstance();// 反射生成一个实例
			System.out.println(id+"实例生成完毕...");
			this.beans.put(id, object);//放入容器
			if(bean.getChild("property")!=null) {
				for(Element property : (List<Element>)bean.getChildren("property")){//遍历所有property
					String name = property.getAttributeValue("name");//获取property下的name
					String beanName = property.getAttributeValue("bean");//获取property下的bean
					System.out.println(id+"中检查到注入bean:"+name);
					Object beanObject = this.beans.get(beanName);//在容器中找到对应的属性
					String methodName = "set" + name.substring(0,1).toUpperCase()+name.substring(1);//拼接set方法名
					System.out.println("set方法名为 :" +methodName);
					Method m = object.getClass().getMethod(methodName, beanObject.getClass().getInterfaces());
					m.invoke(object, beanObject);//调用setter方法
					System.out.println(methodName+"调用完毕");
				}
			}
		}
    }
    
	@Override
	public Object getBean(String beanId) {
		return this.beans.get(beanId);
	}
}
